package com.sz.mes.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.diboot.core.exception.BusinessException;
import com.diboot.core.util.BeanUtils;
import com.diboot.core.util.D;
import com.diboot.core.util.V;
import com.diboot.core.vo.JsonResult;
import com.diboot.core.vo.Status;

import com.diboot.file.controller.BaseExcelFileController;
import com.diboot.file.excel.BaseExcelModel;
import com.diboot.file.excel.listener.ReadExcelListener;
import com.diboot.file.util.ExcelHelper;

import com.sz.mes.entity.Goods;
import com.sz.mes.dto.GoodsDTO;
import com.sz.mes.mapper.GoodsMapper;
import com.sz.mes.service.GoodsService;
import com.sz.mes.vo.GoodsListVO;
import com.sz.mes.excel.listener.GoodsImportListener;
import com.sz.mes.excel.model.GoodsImportModel;
import com.sz.mes.excel.model.GoodsExportModel;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.diboot.iam.annotation.OperationCons;
import com.diboot.iam.annotation.BindPermission;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.stream.Collectors;

/**
 * 商品 Excel处理Controller
 * @author hem
 * @version 1.0
 * @date 2023-12-22
 * Copyright © szhs
 */
@RestController
@RequestMapping("/goods/excel")
@BindPermission(name = "商品导入导出", code = "GoodsExcel")
@Slf4j
public class GoodsExcelController extends BaseExcelFileController {

    @Autowired
    private GoodsService goodsService;

    private final GoodsMapper goodsMapper;

    public GoodsExcelController(GoodsMapper goodsMapper) {
        this.goodsMapper = goodsMapper;
    }

    /**
     * 预览数据
     *
     * @param file
     * @param params
     * @throws Exception
     */
    @BindPermission(name = "导入预览", code = OperationCons.CODE_IMPORT)
    @PostMapping("/preview")
    public JsonResult preview(@RequestParam("file") MultipartFile file, @RequestParam Map<String, Object> params) throws Exception {
//        goodsMapper.truncateAll();
        return super.excelPreview(file, Goods.class, params);
    }

    /**
     * 导入预览保存
     *
     * @param params
     * @throws Exception
     */
    @BindPermission(name = "导入预览保存", code = OperationCons.CODE_IMPORT)
    @PostMapping("/previewSave")
    public JsonResult previewSave(@RequestParam Map<String, Object> params) throws Exception {
        goodsMapper.truncateAll();
        return super.excelPreviewSave(params);
    }

    /**
     * 上传excel并保存
     *
     * @param file
     * @param params
     * @throws Exception
     */
    @BindPermission(name = "直接导入", code = OperationCons.CODE_IMPORT)
    @PostMapping("/upload")
    public JsonResult upload(@RequestParam("file") MultipartFile file, @RequestParam Map<String, Object> params) throws Exception {
        goodsMapper.truncateAll();
        return super.uploadExcelFile(file, Goods.class, params);
    }

    @Override
    protected <T extends BaseExcelModel> void readExcelFile(InputStream inputStream, String fileExt, ReadExcelListener<T> listener) throws Exception {
        try {
            //ExcelHelper.read(inputStream, "csv".equalsIgnoreCase(fileExt) ? ExcelTypeEnum.CSV : null, listener, listener.getExcelModelClass());
            EasyExcel.read(inputStream,listener.getExcelModelClass(),listener).headRowNumber(2).excelType("csv".equalsIgnoreCase(fileExt) ? ExcelTypeEnum.CSV : null).sheet().doRead();
        } catch (Exception var5) {
            log.warn("解析excel文件失败", var5);
            if (var5 instanceof BusinessException) {
                throw var5;
            } else if (V.notEmpty(var5.getMessage())) {
                throw new Exception(var5.getMessage());
            } else {
                throw var5;
            }
        }
    }

    /**
     * 下载示例文件
     *
     * @param response
     * @throws Exception
     */
    @BindPermission(name = "导入商品示例文件下载", code = OperationCons.CODE_IMPORT)
    @GetMapping("/downloadExample")
    public void downloadExample(HttpServletResponse response) throws Exception{
        String fileName = "商品导入示例.xlsx";
        ExcelHelper.exportExcel(response, fileName, GoodsImportModel.class, null);
    }

    /**
     * 商品列表导出
     *
     * @param response
     * @return
     * @throws Exception
     */
    @BindPermission(name = "导出列表文件", code = OperationCons.CODE_EXPORT)
    @GetMapping("/export")
    public JsonResult export(GoodsDTO goodsDto, @RequestParam(value = "columns", required = false) List<String> columns,
    												 HttpServletResponse response) throws Exception{
        QueryWrapper<Goods> queryWrapper = super.buildQueryWrapperByQueryParams(goodsDto);
        List<GoodsListVO> goodsList = goodsService.getViewObjectList(queryWrapper, null, GoodsListVO.class);
        if (V.isEmpty(goodsList)) {
            return new JsonResult(Status.FAIL_OPERATION, "商品列表为空，导出失败");
        }
        String fileName = "商品列表导出_" + D.today() + ".xlsx";
        List<GoodsExportModel> dataList = this.entityList2ExcelList(goodsList);
        ExcelHelper.exportExcel(response, fileName, GoodsExportModel.class, columns, dataList);
        return null;
    }

    /**
     * 实体列表转excel列表
     *
     * @param goodsList
     * @return
     */
    private List<GoodsExportModel> entityList2ExcelList(List<GoodsListVO> goodsList) {
        if (V.isEmpty(goodsList)) {
            return Collections.emptyList();
        }
        return BeanUtils.convertList(goodsList, GoodsExportModel.class);
    }

    @Override
    protected ReadExcelListener<GoodsImportModel> getExcelDataListener() {
        return new GoodsImportListener();
    }

    /**
     * 上传excel并保存
     *
     * @param file
     * @param params
     * @throws Exception
     */
    @BindPermission(name = "重复数据执行更新", code = OperationCons.CODE_IMPORT)
    @PostMapping("/update")
    public JsonResult update(@RequestParam("file") MultipartFile file, @RequestParam Map<String, Object> params) throws Exception {

        ExecutorService threadPool = Executors.newFixedThreadPool(5);
        threadPool.submit(()->{
            ArrayList<GoodsImportModel> goodsImports = new ArrayList<>();
            InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
            EasyExcel.read(inputStream, GoodsImportModel.class, new AnalysisEventListener<GoodsImportModel>() {
                @Override
                public void invoke(GoodsImportModel reportExcel, AnalysisContext analysisContext) {
                    // 将读取到的每一行存入reportDetails集合中
                    goodsImports.add(reportExcel);
                }
                @Override
                public void doAfterAllAnalysed(AnalysisContext analysisContext) {}
            }).sheet().doRead();
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<Goods> allGoods = goodsMapper.selectList(null);
        if (goodsImports.size() > 0) {
            try {
                List<GoodsImportModel> goodsImportModels = BeanUtils.convertList(allGoods, GoodsImportModel.class);
                List<GoodsImportModel> result = goodsImports.stream()
                        .filter(a -> !goodsImportModels.contains(a))
                        .collect(Collectors.toList());
                //后续在此处进行业务处理
                if (result.size() > 0) {
                    for (GoodsImportModel goodsImport : result) {
                        QueryWrapper<Goods> wrapper = new QueryWrapper<>();
                        wrapper.eq("goods_code", goodsImport.getGoodsCode());
                        Goods goods1 = goodsMapper.selectOne(wrapper);
                        Goods goods = BeanUtils.convert(goodsImport, Goods.class);
                        if (goods1 != null) {
                            Long id = goods1.getId();
                            goods.setId(id);
                            goodsMapper.updateById(goods);
                        } else {
                            goodsMapper.insert(goods);
                        }

                    }
                }

            } finally {
                threadPool.shutdown();
            }
        }
        });
        return JsonResult.OK();
    }
}
